package perform.query.builder;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import perform.mappings.ClassMappings;
import perform.type.Type;

public class QueryBuilder {
	
	private static Map<Class<? extends Type>, String> inserts = new HashMap<Class<? extends Type>, String>();
	private static Map<Class<? extends Type>, String> updates = new HashMap<Class<? extends Type>, String>();
	private static Map<Class<? extends Type>, String> deletes = new HashMap<Class<? extends Type>, String>();
	private static Map<Class<? extends Type>, String> retrieves = new HashMap<Class<? extends Type>, String>();
	private static Map<Class<? extends Type>, String> selects = new HashMap<Class<? extends Type>, String>();
	private static Map<Class<? extends Type>, String> froms = new HashMap<Class<? extends Type>, String>();
	
	public static void buildQueries(Class<? extends Type> clazz){
		Map<Field, String> allColumns = ClassMappings.getAllColumns(clazz);
		String idColumn = ClassMappings.getIDColumn(clazz);
		String table = ClassMappings.getTable(clazz);
		inserts.put(clazz, buildInsertQuery(table, allColumns));
		updates.put(clazz, buildUpdateQuery(table, allColumns, idColumn));
		deletes.put(clazz, buildDeleteQuery(table, idColumn));
		retrieves.put(clazz, buildRetrieveQuery(table, idColumn));
		selects.put(clazz, buildSelectQuery(table));
		froms.put(clazz, buildFromQuery(table));
	}
	private static String buildInsertQuery(String table, Map<Field, String> allColumns){
		StringBuilder builder = new StringBuilder("insert into `").append(table).append("` ( `");
		StringBuilder builder2 = new StringBuilder(") values ( ");
		Iterator<Field> fields = allColumns.keySet().iterator();
		while(fields.hasNext()){
			Field field = fields.next();
			builder.append(allColumns.get(field)).append("` , `");
			builder2.append("? , ");
		}
		builder.replace(builder.lastIndexOf(","), builder.length(), 
				builder2.replace(builder2.lastIndexOf(","), builder2.length(), ") ;").toString());
		return builder.toString();
	}
	private static String buildUpdateQuery(String table, Map<Field, String> allColumns, String idColumn){
		StringBuilder builder = new StringBuilder("update `").append(table).append("` set `");
		Iterator<Field> fields = allColumns.keySet().iterator();
		while(fields.hasNext()){
			builder.append(allColumns.get(fields.next())).append("` = ? , `");
		}
		builder.replace(builder.lastIndexOf(","), builder.length(), "where `")
				.append(idColumn).append("` = ? ");
		return builder.toString();
	}
	private static String buildDeleteQuery(String table, String idColumn){
		StringBuilder builder = new StringBuilder("delete from `").append(table)
				.append("` where `").append(idColumn).append("` = ? ;");
		return builder.toString();
	}
	private static String buildRetrieveQuery(String table, String idColumn){
		StringBuilder builder = new StringBuilder("select * from `").append(table)
				.append("` where `").append(idColumn).append("` = ? ;");
		return builder.toString();
	}
	private static String buildSelectQuery(String table){
		StringBuilder builder = new StringBuilder("select * from `")
				.append(table).append("` where ");
		return builder.toString();
	}
	private static String buildFromQuery(String table){
		StringBuilder builder = new StringBuilder("select `")
				.append(table).append("`.* ");
		return builder.toString();
	}
	
	public static String getInsertQuery(Class<? extends Type> clazz){
		return inserts.get(clazz);
	}
	public static String getUpdateQuery(Class<? extends Type> clazz){
		return updates.get(clazz);
	}
	public static String getDeleteQuery(Class<? extends Type> clazz){
		return deletes.get(clazz);
	}
	public static String getRetrieveQuery(Class<? extends Type> clazz){
		return retrieves.get(clazz);
	}
	public static String getSelectQuery(Class<? extends Type> clazz){
		return selects.get(clazz);
	}
	public static String getFromQuery(Class<? extends Type> clazz){
		return froms.get(clazz);
	}

}
